package com.qp.basics.estivate;

import com.qp.basics.estivate.support.DriverConnectionProvider;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * 工具类。
 */
public class DbHelper {
	/**
	 * clob到字符串。
	 * 
	 * @param c
	 * @return
	 * @throws Exception
	 */
	public static String clobToString(Clob c) {
		StringWriter sw = new StringWriter();
		Reader r = null;
		try {
			r = (Reader) c.getCharacterStream();
			char[] chars = new char[1024];
			int i = 0;
			while ((i = r.read(chars)) > 0) {
				sw.write(chars, 0, i);
			}
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			if (r != null)
				try {
					r.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		String str = sw.toString();
		return str;
	}

	static List<Database> createDatabase(Map dbXmlMap)
			throws InstantiationException, IllegalAccessException,
			ClassNotFoundException {

		String type = (String) dbXmlMap.get("type");
		
		DriverConnectionProvider cp = new DriverConnectionProvider();
		cp.setDriver((String) dbXmlMap.get("driver"));
		cp.setPassword((String) dbXmlMap.get("password"));
		cp.setUser((String) dbXmlMap.get("user"));
		cp.setUrl((String) dbXmlMap.get("url"));

		String importAll = (String) dbXmlMap.get("importAll");

		List<Database> dbList = new ArrayList<Database>();

		Database db = BaseDatabase.getDatabaseByType(type);

		if (db != null) {
			db.setConnectionProvider(cp);
			db.setDatabaseName((String) dbXmlMap.get("name"));
			if (StringUtils.isNotBlank(importAll)) {
				dbList = db.getAvailableDatabases();
			}else{
				db.setTableSchema((String) dbXmlMap.get("schema"));
				dbList.add(db);
			}

			for(Database dbItem : dbList){
				
				dbItem.setDescription((String) dbXmlMap.get("description"));
				dbItem.setVersion((String) dbXmlMap.get("version"));
				
				Table[] tables = dbItem.getTables();
				Arrays.sort(tables, new Comparator<Table>() {
					public int compare(Table t1, Table t2) {
						return t1.getTableName().compareTo(t2.getTableName());
					}
				});
			}
		}

		return dbList;
	}

	/**
	 * 拆分sql。
	 * 
	 * @param sqlsStr
	 * @return
	 */
	public static String[] splitSqls(String sqlsStr) {
		char[] chars = sqlsStr.toCharArray();
		List<String> sqls = new ArrayList();
		boolean inStr = false;
		int index = 0;
		for (int i = 0; i < chars.length; i++) {
			char c = chars[i];
			if (c == '\\') {
				i++;
				continue;
			} else if (c == '\'') {
				if (inStr) {
					inStr = false;
				} else {
					inStr = true;
				}
			} else if (c == ';') {
				if (!inStr) {
					String sql = new String(chars, index, i - index);
					if (sql.trim().length() > 0)
						sqls.add(sql);
					index = i + 1;
				}
			}
		}
		String sql = new String(chars, index, chars.length - index);
		if (sql.trim().length() > 0)
			sqls.add(sql);
		String[] rtn = new String[sqls.size()];
		return sqls.toArray(rtn);
	}

	/**
	 * 拷贝自spring的代码，但除去了对Blob和Clob的自动处理，因为担心内容太大带来一些问题，还是 让调用端程序自己处理吧。
	 * 
	 * @param rs
	 * @param index
	 * @return
	 * @throws SQLException
	 */
	public static Object getResultSetValue(ResultSet rs, int index)
			throws SQLException {
		Object obj = rs.getObject(index);
		String className = null;
		if (obj != null) {
			className = obj.getClass().getName();
		}
		// if (obj instanceof Blob) {
		// obj = rs.getBytes(index);
		// }
		// else if (obj instanceof Clob) {
		// obj = rs.getString(index);
		// }
		// else
		if (className != null
				&& ("oracle.sql.TIMESTAMP".equals(className) || "oracle.sql.TIMESTAMPTZ"
						.equals(className))) {
			obj = rs.getTimestamp(index);
		} else if (className != null && className.startsWith("oracle.sql.DATE")) {
			String metaDataClassName = rs.getMetaData().getColumnClassName(
					index);
			if ("java.sql.Timestamp".equals(metaDataClassName)
					|| "oracle.sql.TIMESTAMP".equals(metaDataClassName)) {
				obj = rs.getTimestamp(index);
			} else {
				obj = rs.getDate(index);
			}
		} else if (obj != null && obj instanceof java.sql.Date) {
			if ("java.sql.Timestamp".equals(rs.getMetaData()
					.getColumnClassName(index))) {
				obj = rs.getTimestamp(index);
			}
		}
		return obj;
	}

}
